<template>
    <div class="demo"> 
        <h5>watch情况一：【ref】定义的【基本类型】数据</h5>
        <h6>当前累加：{{sum}}</h6>
        <button @click="changeSum">sum+1</button>
        
        <hr/>
        <h5>watch情况二：【ref】定义的【对象类型】数据</h5>
        <h6>姓名：{{person.name}}</h6>
        <h6>年龄：{{person.age}}</h6>
        <button @click="changeName">修改名字</button>
        <button @click="changeAge">修改年龄</button>
        <button @click="changePerson">修改人</button>
          
        <hr/>
        <h5>watch情况三：【reactive】定义的【对象类型】数据</h5>
        <h6>姓名：{{people.name}}</h6>
        <h6>年龄：{{people.age}}</h6>
        <button @click="modifyName">修改名字</button>
        <button @click="modifyAge">修改年龄</button>
        <button @click="modifyPeople">修改人</button>
        
        <hr/>
        <h5>watch情况四：ref或reactive定义的【对象类型】数据，数据中某个属性</h5>
        <h6>姓名：{{person2.name}}</h6>
        <h6>年龄：{{person2.age}}</h6>
        <h6>坐骑：{{person2.car.c1}}、{{person2.car.c2}}</h6>
        <button @click="changeName2">修改名字</button>
        <button @click="changeAge2">修改年龄</button>
        <button @click="changeFirstCar">修改第一台车</button>
        <button @click="changeSecCar">修改第二台车</button>
        <button @click="changeCar">修改整个车</button>
        
        <hr/>
        <h5>watch情况五：上述多个数据</h5>
        <h6>姓名：{{person2.name}}</h6>
        <h6>年龄：{{person2.age}}</h6>
        <h6>坐骑：{{person2.car.c1}}、{{person2.car.c2}}</h6>
        <button @click="changeName2">修改名字</button>
        <button @click="changeAge2">修改年龄</button>
        <button @click="changeFirstCar">修改第一台车</button>
        <button @click="changeSecCar">修改第二台车</button>
        <button @click="changeCar">修改整个车</button>
        
        <hr/>
        <h5>watchEffect</h5>
        <h6>需求：当水温达到90度，或者水位达到66cm时，给服务器发送请求</h6>
        <h6>当前水温：{{temp}}</h6>
        <h6>当前水位：{{height}}</h6>
        <button @click="incrTemp">点我+10</button>
        <button @click="incrHeight">点我+2</button>
    </div>
    

</template>
<!---
1.简介
watch :监听数据变化
vue3中的watch只能监测以下四种数据
a.ref 定义的数据
b.reactive 定义的数据
c.函数返回值（getter函数）
d.计算属性一个包含上述内容的数据

2.watch的5种场景
a.监视ref定义的【基本类型】数据，直接写数据名即可监视是其value值的改变


3.watch和watchEffect 区别
watchEffect:立即运行一个函数，同时响应式地追踪依赖，并在依赖更改时重新执行该函数

watch与watchEffect对比
watch: 适合监听多个数据，且数据之间有依赖关系，要明确支出某个数据
watchEffect: 适合监听单个数据，且数据之间没有依赖关系

-->

<script lang="ts" setup>
    import {ref,reactive,watch,watchEffect} from 'vue' 
/********************watch情况一：【ref】定义的【基本类型】数据***************************/    
    let sum = ref(0);
    function changeSum(){
        sum.value++;
    }
    //
    /* watch(sum, (newValue, oldValue) => {
        console.log("sum值改变", newValue, oldValue);
    }); */
    //解除监视方法：
    const stopWatch = watch(sum, (newValue, oldValue) => {
        console.log("sum值改变", newValue, oldValue);
        if(newValue > 10){
            stopWatch(); //调用自身结束监视
        }
    });
    

/********************watch情况二：【ref】定义的【对象类型】数据***************************/    
let person = ref({
    name:'张三',
    age:18
 });
 function changeName(){
     person.value.name += "*"
 }
 function changeAge(){
     person.value.age += 1
 }
 function changePerson(){
     person.value = {
         name:'王五',
         age:20
     }
 }
/*  watch(person.value, (newValue, oldValue) => {
     console.log("person值改变", newValue, oldValue);
 }); */
 //深层监视 
 //开启深层监视只需写对象，可监测到对象内部属性的修改
 watch(person, (newValue, oldValue) => {
     console.log("person值改变", newValue, oldValue);
 },{deep:true});
 
 

/********************watch情况三：【reactive】定义的【对象类型】数据***************************/
//reactive 默认开启深度监视    
 let  people = reactive({
     name:'石昊',
     age:18
 });
 function modifyName(){
     people.name += "*"
 }
 function modifyAge(){
     people.age += 1
 }
 function modifyPeople(){
    
     Object.assign(people,{
         name:'石毅',
         age:20
     })
    
 }
 watch(people, (newValue, oldValue) => {
     console.log("people值改变", newValue, oldValue);
 });
 
 /********************watch情况四：ref或reactive定义的【对象类型】数据，数据中某个属性***************************/   
/*
监视ref或reactive定义的【对象类型】数据，数据中某个属性，注意：
1.若属性值不是对象类型，需要写成函数形式
2.若属性值依然是【对象类型】，可直接调用，也可写成函数，不建议写成函数

监视的是对象里的属性，最好写函数式；若是对象监视的是地址值，需要关注对象内部，
需要手动开启深度监视
*/
let  person2 = reactive({
     name:'张三',
     age:18,
     car:{
         c1:'奔驰',
         c2:'宝马'
     }
 });
 function changeName2(){
     person2.name += "*"
 }
 function changeAge2(){
     person2.age += 1
 }
 function changeFirstCar(){
     person2.car.c1 = "奥迪"
 }
 function  changeSecCar(){
     person2.car.c2 = "大众"
 }
 function changeCar(){
     person2.car = {
         c1:'特斯拉',
         c2:'红旗'   
         }
 }
 /*
watch(person2, (newValue, oldValue) => {
     console.log("people值改变", newValue, oldValue);
 });
 */
//基本类型
 //监听对象属性,需要将属性转为一个函数
watch(()=>{return person2.name}, (newValue, oldValue) => {
     console.log("person2.name值改变", newValue, oldValue);
 });
//语法糖
watch(()=>person2.age, (newValue, oldValue) => {
     console.log("person2.age值改变", newValue, oldValue);
 });
 
 //对象类型（直接写和函数式都行）
 watch(person2.car, (newValue, oldValue) => {
     console.log("person2.car值改变", newValue, oldValue);
 });
 //推荐写函数
watch(()=>person2.car, (newValue, oldValue) => {
     console.log("person2.car值改变", newValue, oldValue);
 },{deep:true});
 
 watch(()=>person2.car.c1, (newValue, oldValue) => {
     console.log("person2.car.c1值改变", newValue, oldValue);
 });

 
/********************watch情况五：监视上述多个数据***************************/ 
watch([
    ()=>person2.name,
    ()=>person2.age,
    ()=>person2.car,
    ()=>person2.car.c1,
    ()=>person2.car.c2
], (newValue, oldValue) => {
     console.log("person3值改变", newValue, oldValue);
 },{deep:true});  


/********************watchEffect***************************/
let temp = ref(10);
let height = ref(20);
function incrTemp(){
    temp.value += 10;
}
function incrHeight(){
    height.value += 2;
}
//监视
//watch的实现
/*
watch([temp,height],(value)=>{
    //从value中获取最新的水温和水位
    let  [newTemp,newHeight] = value;
    if(newTemp >= 90 || newHeight >= 66){
        alert("水温或水位过高！");
    }
})
*/

///watchEffect实现
watchEffect(()=>{
    if(temp.value >= 90 || height.value >= 66){
        alert("水温或水位过高！");
    }
})
</script>

<style>
    .demo {
        background-color: skyblue;
        box-shadow: 0 0 10px;
        border-radius: 10px;
        padding: 10px;
        width: 550px;
        margin: 10px;
    }
    button  { 
        margin: 5px 5px;

    }

</style>